package com.ruoyi.web.ydz.util.messageUtil;

import com.alibaba.fastjson2.JSONObject;
import com.aliyun.tea.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.SysRegisterService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.ydz.domain.SmsVerification;
import com.ruoyi.web.ydz.service.ISmsVerificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.time.DayOfWeek;
import java.time.LocalDate;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.regex.Pattern;

import static com.ruoyi.common.core.domain.AjaxResult.error;
import static com.ruoyi.common.core.domain.AjaxResult.success;
import static com.ruoyi.common.utils.SecurityUtils.getLoginUser;

@Component
public class SendSms extends BaseEntity {

    /**
     * <b>description</b> :
     * <p>使用AK&amp;SK初始化账号Client</p>
     *
     * @return Client
     * @throws Exception
     */

    @Value("${aliyun.ALIBABA_CLOUD_ACCESS_KEY_ID}")
    private String ALIBABA_CLOUD_ACCESS_KEY_ID;

    @Value("${aliyun.ALIBABA_CLOUD_ACCESS_KEY_SECRET}")
    private String ALIBABA_CLOUD_ACCESS_KEY_SECRET;

    /*通用模板*/
    @Value("${aliyun.GENERAL_CODE}")
    private String GENERAL_CODE;

    /*登录模板*/
    @Value("${aliyun.LOGIN_CODE}")
    private String LOGIN_CODE;

    /*找回密码模板*/
    @Value("${aliyun.RETRIEVE_PASSWORD_CODE}")
    private String RETRIEVE_PASSWORD_CODE;

    /*注册模板*/
    @Value("${aliyun.REGISTER_CODE}")
    private String REGISTER_CODE;

    /*短信签名*/
    @Value("${aliyun.SIGNATURE}")
    private String SIGNATURE;

    @Resource
    private ISmsVerificationService smsVerificationService;

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private TokenService tokenService;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private SysRegisterService sysRegisterService;

    @Resource
    private SysPermissionService permissionService;

    @Resource
    private ISysUserService userService;

    public com.aliyun.dysmsapi20170525.Client createClient() throws Exception {

        // 工程代码泄露可能会导致 AccessKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考。
        // 建议使用更安全的 STS 方式，更多鉴权访问方式请参见：https://help.aliyun.com/document_detail/378657.html。
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
                .setAccessKeyId(ALIBABA_CLOUD_ACCESS_KEY_ID)
                // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
                .setAccessKeySecret(ALIBABA_CLOUD_ACCESS_KEY_SECRET);
        // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new com.aliyun.dysmsapi20170525.Client(config);
    }

    public JSONObject sendMessage(SmsVerification smsVerification) throws Exception {
        JSONObject responseJson = new JSONObject();

        if (Objects.isNull(smsVerification.getPhone()) || !StringUtils.isEmpty(smsVerification.getPhone())) {
            responseJson.put("code", "200");
            responseJson.put("msg", "请输入正确的手机号码");
        }
        if (!isValidPhoneNumber(smsVerification.getPhone())) {
            responseJson.put("code", "200");
            responseJson.put("msg", "请输入正确的手机号码");
        }
        String template_code = "";
        switch (smsVerification.getOperateId().intValue()) {
            case 1:
                template_code = GENERAL_CODE;
                break;
            case 2:
                template_code = LOGIN_CODE;
                break;
            case 3:
                template_code = RETRIEVE_PASSWORD_CODE;
                break;
            case 4:
                template_code = REGISTER_CODE;
                break;
            default:
                template_code = GENERAL_CODE;
        }

        com.aliyun.dysmsapi20170525.Client client = this.createClient();

        /*生成随机验证码*/
        String randomNumber = String.valueOf(new Random().nextInt(900000) + 100000);
        com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
                .setSignName(SIGNATURE)
                .setTemplateParam("{\"code\":\"" + randomNumber + "\"}")
                .setPhoneNumbers(smsVerification.getPhone())
                .setTemplateCode(template_code);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            // 复制代码运行请自行打印 API 的返回值
            client.sendSmsWithOptions(sendSmsRequest, runtime);

            smsVerification.setCode(randomNumber);
            smsVerification.setCreateTime(DateUtils.getNowDate());
            smsVerificationService.insertSmsVerification(smsVerification);

            responseJson.put("code", 200);
            responseJson.put("msg", "验证码发生成功");
            responseJson.put("data", smsVerification.getId());
            return responseJson;
        } catch (TeaException error) {
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            com.aliyun.teautil.Common.assertAsString(error.message);
            responseJson.put("code", 500);
            responseJson.put("msg", error.getData().get("Recommend"));
            return responseJson;
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            com.aliyun.teautil.Common.assertAsString(error.message);
            responseJson.put("code", 500);
            responseJson.put("msg", error.getData().get("Recommend"));
            return responseJson;

        }
    }

    /*手机号码验证*/
    public static boolean isValidPhoneNumber(String phoneNumber) {
        // 正则表达式：以 1 开头，后面跟着 10 位数字
        String regex = "^1\\d{10}$";
        return Pattern.matches(regex, phoneNumber);
    }

    /*校验验证码*/
    public AjaxResult proofCode(SmsVerification smsVerification) {
        AjaxResult ajaxResult = new AjaxResult();
        if (!Objects.isNull(smsVerification.getId())) {
            SmsVerification oldSms = smsVerificationService.selectSmsVerificationById(smsVerification.getId());
            if (!Objects.isNull(oldSms)) {

                if (!Objects.isNull(smsVerification.getCode()) && !Objects.isNull(smsVerification.getPhone())) {
                    if (smsVerification.getCode().equals(oldSms.getCode()) && smsVerification.getPhone().equals(oldSms.getPhone())) {

                        Date createTime = oldSms.getCreateTime();
                        Date now = new Date();
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(now);
                        calendar.add(Calendar.MINUTE, -5); // 当前时间减去5分钟
                        Date fiveMinutesAgo = calendar.getTime();

                        if (createTime.after(fiveMinutesAgo)) {
                            ajaxResult.put("code", 200);
                            ajaxResult.put("msg", "验证成功");
                            ajaxResult.put("data", true);
                        } else {
                            ajaxResult.put("code", 200);
                            ajaxResult.put("msg", "验证码超时,请重新获取");
                            ajaxResult.put("data", false);
                        }

                    } else {
                        ajaxResult.put("code", 200);
                        ajaxResult.put("msg", "验证码有误");
                        ajaxResult.put("data", false);
                    }
                } else {
                    ajaxResult.put("code", 200);
                    ajaxResult.put("msg", "请输入正确手机号或验证码");
                    ajaxResult.put("data", false);
                }
            } else {
                ajaxResult.put("code", 200);
                ajaxResult.put("msg", "暂无验证码信息");
                ajaxResult.put("data", false);
            }

        } else {
            ajaxResult.put("code", 200);
            ajaxResult.put("msg", "暂无验证码信息");
            ajaxResult.put("data", false);
        }
        return ajaxResult;
    }

    /*内置登录操作*/
    public String login(String username) {
        // 用户验证
        LoginUser loginUser = new LoginUser();
        SysUser sysUser = sysUserService.selectUserByname(username);
        loginUser.setUser(sysUser);
        loginUser.setUserId(sysUser.getUserId());
        loginUser.setDeptId(sysUser.getDeptId());

        /*赋予权限*/
        Set<String> rolePermission = permissionService.getMenuPermission(sysUser);
        loginUser.setPermissions(rolePermission);

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        loginService.recordLoginInfo(loginUser.getUserId());
        String token = tokenService.createToken(loginUser);

        return token;
    }

    /*修改账户绑定手机号码*/
    public AjaxResult changePhoneNum(SmsVerification smsVerification) {
        AjaxResult responseAjax = new AjaxResult();
        AjaxResult ajaxResult = this.proofCode(smsVerification);

        if (Boolean.parseBoolean(String.valueOf(ajaxResult.get("data")))) {

            /*更换手机号码和userName*/
            LoginUser loginUser = getLoginUser();
            SysUser currentUser = loginUser.getUser();
            currentUser.setPhonenumber(smsVerification.getPhone());
            currentUser.setUserName(smsVerification.getPhone());

            if (StringUtils.isEmpty(currentUser.getPhonenumber()) || !userService.checkPhoneUnique(currentUser) || !userService.checkUserNameUnique(currentUser))
            {
                return error("修改用户'" + loginUser.getUsername() + "'失败，手机号码已存在");
            }

            if (userService.updateUserProfile(currentUser) > 0) {
                // 更新缓存用户信息
                tokenService.setLoginUser(loginUser);
                return success();
            }

        } else {
            return ajaxResult;
        }
        return responseAjax;
    }

    /*手机号码登录*/
    public AjaxResult phoneLogin(SmsVerification smsVerification) {
        AjaxResult responseAjax = new AjaxResult();
        AjaxResult ajaxResult = this.proofCode(smsVerification);
        if (Boolean.parseBoolean(String.valueOf(ajaxResult.get("data")))) {
            SysUser sysUser = sysUserService.selectUserByname(smsVerification.getPhone());
            /*登录*/
            if (!Objects.isNull(sysUser) && !Objects.isNull(sysUser.getPassword())) {
                String token = this.login(smsVerification.getPhone());
                responseAjax.put("msg", "操作成功");
                responseAjax.put("code", 200);
                responseAjax.put(Constants.TOKEN, token);

            } else {
                /*注册*/
                RegisterBody registerBody = new RegisterBody();
                registerBody.setUsername(smsVerification.getPhone());
                registerBody.setPassword(UUID.randomUUID().toString().replace("-", "").substring(0, 8));
                sysRegisterService.register(registerBody, "");

                String token = this.login(smsVerification.getPhone());
                responseAjax.put("msg", "操作成功");
                responseAjax.put("code", 200);
                responseAjax.put(Constants.TOKEN, token);
            }

        } else {
            return ajaxResult;
        }
        return responseAjax;
    }

    /*获取传入时间与当前时间的距离秒*/
    public Long getDateDifference(Date requestDate) {
        Date currentTime = new Date();

        Instant currentInstant = currentTime.toInstant();
        Instant remindInstant = requestDate.toInstant();

        // 计算时间差
        Duration duration = Duration.between(currentInstant, remindInstant);

        // 获取秒数
        long secondsUntilRemind = duration.getSeconds();

        return secondsUntilRemind;
    }

    /*获取当前自然星期 一整个星期的年月日*/
    public List<Date> getCurrentWeek() {
        // 获取当前日期
        LocalDate today = LocalDate.now();

        // 获取当前周的星期一
        LocalDate startOfWeek = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));

        // 存储当前星期的LIST
        List<Date> weekDates = new ArrayList<>();

        for (int i = 0; i < 7; i++) {
            LocalDate currentDay = startOfWeek.plusDays(i);
            Date date = java.sql.Date.valueOf(currentDay);
            weekDates.add(date);
        }

        return weekDates;
    }
}